`include "ExceptStruct.vh"
`include "CSRStruct.vh"
`include "RegStruct.vh"
`include "TimerStruct.vh"
`include "Defines.vh"
module Core (
    input wire clk,                       /* 时钟 */ 
    input wire rstn,                       /* 重置信号 */ 

    output wire [63:0] pc,                /* current pc */
    input wire [31:0] inst,               /* read inst from ram */

    output wire [63:0] address,           /* memory address */
    output wire we_mem,                   /* write enable */
    output wire [63:0] wdata_mem,         /* write data to memory */
    output wire [7:0] wmask_mem,          /* write enable for each byte */ 
    output wire re_mem,                   /* read enable */
    input wire [63:0] rdata_mem,          /* read data from memory */

    input wire if_stall,
    input wire mem_stall,
    output wire if_request,
    output wire switch_mode,

    input TimerStruct::TimerPack time_out,

    output cosim_valid,
    output [63:0] cosim_pc,          /* current pc */
    output [31:0] cosim_inst,        /* current instruction */
    output [ 7:0] cosim_rs1_id,      /* rs1 id */
    output [63:0] cosim_rs1_data,    /* rs1 data */
    output [ 7:0] cosim_rs2_id,      /* rs2 id */
    output [63:0] cosim_rs2_data,    /* rs2 data */
    output [63:0] cosim_alu,         /* alu out */
    output [63:0] cosim_mem_addr,    /* memory address */
    output [ 3:0] cosim_mem_we,      /* memory write enable */
    output [63:0] cosim_mem_wdata,   /* memory write data */
    output [63:0] cosim_mem_rdata,   /* memory read data */
    output [ 3:0] cosim_rd_we,       /* rd write enable */
    output [ 7:0] cosim_rd_id,       /* rd id */
    output [63:0] cosim_rd_data,     /* rd data */
    output [ 3:0] cosim_br_taken,    /* branch taken? */
    output [63:0] cosim_npc,         /* next pc */
    output CSRStruct::CSRPack cosim_csr_info,
    output RegStruct::RegPack cosim_regs,

    output cosim_interrupt,
    output [63:0] cosim_cause
);


// assign pc = IF_pc;
// assign address = rw_addr;
// assign we_mem = MEM_we_mem;
// assign re_mem = MEM_re_mem;
// assign wdata_mem = rw_wdata;
// assign wmask_mem = rw_wmask;
// assign if_request = 1'b1;
// assign rw_rdata = rdata_mem;
wire if_request_cpu;
assign if_request_cpu=~(
        
        ID_inst==`ECALL|ID_inst==`MRET|
        EXE_inst==`ECALL|EXE_inst==`MRET|
        MEM_inst==`ECALL|MEM_inst==`MRET|
        WB_inst==`ECALL|WB_inst==`MRET
        // (EXE_csr_we&&EXE_inst[31:20]==12'h180)|
        // (ID_csr_we&&ID_inst[31:20]==12'h180)
    );


wire maybe_jump = ID_inst[6:0]==7'b1100011|
        ID_inst[6:0]==7'b1101111|
        ID_inst[6:0]==7'b1100111|ID_inst==`ECALL|ID_inst==`MRET|
        EXE_inst==`ECALL|EXE_inst==`MRET|
        MEM_inst==`ECALL|MEM_inst==`MRET|
        WB_inst==`ECALL|WB_inst==`MRET;

import ExceptStruct::*;
wire rst=~rstn;
ExceptStruct::ExceptPack ID_except='{except: 1'b0, epc:64'b0, ecause:64'b0,
etval: 64'b0};
ExceptStruct::ExceptPack EXE_except;
ExceptStruct::ExceptPack MEM_except;
ExceptStruct::ExceptPack WB_except;


/* SIM output */
assign cosim_valid=WB_valid & ~cosim_interrupt;
assign cosim_pc=WB_pc;      
assign cosim_inst=WB_inst;
assign cosim_rd_we={3'b0,WB_we_reg};
assign cosim_rd_id={3'b0,WB_inst[11:7]}; 
assign cosim_rd_data=dataW;
assign cosim_npc=IF_npc;

wire is_sfence = (ID_inst == 12000073);
wire if_stall_cpu,mem_stall_cpu;
MMU mmu(
        .rst(rst),
        .clk(clk),
        .satp(cosim_csr_info.satp),
        .maybe_jump(maybe_jump),
        .is_ecall(is_ecall_id),
        .is_mret(ID_inst==32'h30200073),

        .tlb_flush(is_sfence),
        .if_stall_from_mem(if_stall),
        .if_stall_to_cpu(if_stall_cpu),
        .mem_stall_from_mem(mem_stall),
        .mem_stall_to_cpu(mem_stall_cpu),

        .pc_from_cpu(IF_pc),
        .pc_to_mem(pc),

        .if_request_from_cpu(if_request_cpu),
        .if_request_to_mem(if_request),

        .inst_from_mem(inst),
        .inst_to_cpu(IF_inst),

        .address_from_cpu(rw_addr),
        .address_to_mem(address),

        .re_mem_from_cpu(MEM_re_mem),
        .re_mem_to_mem(re_mem),
        
        .rdata_mem_to_cpu(rw_rdata),
        .rdata_mem_from_mem(rdata_mem),

        .we_mem_from_cpu(MEM_we_mem),
        .we_mem_to_mem(we_mem),

        .wdata_mem_from_cpu(rw_wdata),
        .wdata_mem_to_mem(wdata_mem),

        .wmask_mem_from_cpu(rw_wmask),
        .wmask_mem_to_mem(wmask_mem),

        .jump(jump),
        .M_mode(M_mode)
    );

/*----------------------------------------Race control decoder----------------------------------------*/

wire            PC_stall,IFID_stall,IDEXE_stall,EXEMEM_stall,MEMWB_stall;
wire            IFID_flush, IDEXE_flush, EXEMEM_flush, MEMWB_flush;
wire            jump;
wire  [63:0]    Forward_data1,Forward_data2;
wire            ForwardA , ForwardB;
assign          jump = EXE_npc_sel & EXE_br_taken | switch_mode;
Race_controller racectrl(
        .clk(clk),
        .jump(jump),
        .if_stall(if_stall_cpu),
        .mem_stall(mem_stall_cpu),
        .predict_jump_exe(predict_jump_exe),
        .switch_mode(switch_mode),

        .PC_stall(PC_stall),
        .IFID_stall(IFID_stall),
        .IDEXE_stall(IDEXE_stall),
        .EXEMEM_stall(EXEMEM_stall),
        .MEMWB_stall(MEMWB_stall),
        .IFID_flush(IFID_flush),
        .IDEXE_flush(IDEXE_flush),
        .EXEMEM_flush(EXEMEM_flush),
        .MEMWB_flush(MEMWB_flush)
);//竞争处理控制模块


/*----------------------------------------Forwarding unit----------------------------------------*/

Forwarding_unit Forwarding(
        .ID_inst(ID_inst),
        .EXE_inst(EXE_inst),
        .MEM_inst(MEM_inst),
        .WB_inst(WB_inst),
        .EXE_rs1_use(EXE_rs1_use),
        .EXE_rs2_use(EXE_rs2_use),
        .MEM_wb_sel(MEM_wb_sel),
        .MEM_we_reg(MEM_we_reg),
        .WB_we_reg(WB_we_reg),
        .MEM_alu_res(MEM_csr_res),
        .MEM_mem(MEM_mem),
        .dataW(dataW),
        .MEM_csr_we(MEM_csr_we),
        .MEM_csr_val(MEM_csr_val),
        .MEM_csr_res(MEM_csr_res),

        .Forward_data1(Forward_data1),
        .Forward_data2(Forward_data2),
        .ForwardA(ForwardA),
        .ForwardB(ForwardB)
);



/*----------------------------------------IF----------------------------------------*/

wire   [63:0]    IF_pc_4;                    //IF_PC+4
wire   [63:0]    IF_pc;
wire   [63:0]    IF_npc;
wire   [31:0]    IF_inst;                    //指令
wire             IF_valid = 1'b1;
logic            predict_jump_if;
logic            predict_jump_id;
logic            predict_jump_exe;
wire   [63:0]    pc_target_if;
wire             predict_wrong = (jump != predict_jump_exe);
//assign          ro_addr = (jump?EXE_alu_res:(PC_stall ? IF_pc:IF_npc)) >>3;

BranchPrediction branchpredict(
        .clk(EXE_pc!=0),
        .rst(rst),
        .pc_if(IF_pc),
        .jump_if(predict_jump_if),
        .pc_target_if(pc_target_if),

        .inst_exe(EXE_inst),
        .pc_exe(EXE_pc),
        .pc_target_exe(EXE_alu_res),
        .jump_exe(predict_jump_exe),
        .is_jump_exe(jump)
);

pc_mux pcmux(
          .jump(jump),
          .pc_4(IF_pc_4),
          .alu_res(EXE_alu_res),
          .predict_jump_if(predict_jump_if),
          .predict_jump_exe(predict_jump_exe),
          .switch_mode(switch_mode),
          .pc_csr(csr_call_pc),
          .pc_target_if(pc_target_if),
          .EXE_pc(EXE_pc),
          .stall(PC_stall),
          .npc(IF_npc)
);//PC选择



PC VPC(
        .clk(clk),
        .rst(rst),
        .stall(PC_stall),
        .npc(IF_npc),
        .switch_mode(switch_mode),
        .if_stall(if_stall_cpu),
        .predict_jump_exe(predict_jump_exe),
        .EXE_pc(EXE_pc),
        .alu_res(EXE_alu_res),
        .jump(jump),
        .pc_csr(csr_call_pc),

        .IF_pc(IF_pc),
        .IF_pc_4(IF_pc_4)
);


/*
RAM IMEM
*/

/*IF阶段的IMEM与访存阶段的DMEM都在MEM模块中*/

/* AXI4 去掉此处
instselect inst_select(
        .pc(IF_pc),
        .ro_rdata(ro_rdata),
        .inst(IF_inst),
        .jump(jump),
        .valid(IF_valid)
);//select the instruction
*/
/*----------------------------------------IF/ID----------------------------------------*/

IFID IF_ID(
        .clk(clk),
        .rst(rst),
        .stall(IFID_stall),
        .flush(IFID_flush),
        .IF_pc(IF_pc),
        .IF_inst(IF_inst),
        .IF_valid(IF_valid),
        .IF_pc_4(IF_pc_4),
        .predict_jump_if(predict_jump_if),

        .ID_inst(ID_inst),
        .ID_pc(ID_pc),
        .ID_pc_4(ID_pc_4),
        .ID_valid(ID_valid),
        .predict_jump_id(predict_jump_id)
);

/*----------------------------------------ID----------------------------------------*/
wire  [63:0] dataW;
wire  [63:0] rrs1,rrs2;
wire  [2:0]  immgen_op;
wire  [63:0] imm_data;

wire  [63:0] ID_pc;
wire  [31:0] ID_inst;
wire         ID_valid;
wire  [63:0] ID_data1;
wire  [63:0] ID_data2;
wire  [4:0]  ID_rs1;
wire  [4:0]  ID_rs2;
wire  [4:0]  ID_rd;
wire  [63:0] ID_imm;
wire         ID_rs1_use;
wire         ID_rs2_use;
wire         ID_we_reg;
wire         ID_we_mem;
wire  [3:0]  ID_alu_op;
wire  [2:0]  ID_bralu_op;
wire  [1:0]  ID_alu_asel;
wire  [1:0]  ID_alu_bsel;
wire  [1:0]  ID_wb_sel;
wire  [2:0]  ID_data_width;
wire  [63:0] ID_pc_4;
wire  [2:0]  ID_immgen_op;
wire         ID_npc_sel;
wire         ID_re_mem;
wire  [63:0] reg_data1;
wire  [63:0] reg_data2;


wire         except_happen_id;
wire  [1:0]  priv;
wire  [25:0] decode;                     //控制模块解码
wire  mret = (WB_inst == 32'h30200073 );
wire  sret = (WB_inst == 32'h10200073 );
wire  [1:0]  csr_ret_wb = {mret,sret};
wire  [63:0] csr_call_pc;
wire  [63:0] ID_csr_val;
wire         ID_csr_we;
wire         EXE_csr_we;
wire         MEM_csr_we;
wire         WB_csr_we;
// wire         cosim_interrupt;
// wire  [63:0] cosim_cause;
// CSRStruct::CSRPack cosim_csr_info;

assign ID_we_reg  = decode[21];
assign ID_we_mem  = decode[20];
assign ID_npc_sel = decode[19];
assign ID_immgen_op = decode[18:16];
assign ID_alu_op  = decode[15:12];
assign ID_bralu_op = decode[11:9];
assign ID_alu_asel = decode[8:7];
assign ID_alu_bsel = decode[6:5];
assign ID_wb_sel = decode[4:3];
assign ID_data_width = decode[2:0];
assign ID_rs1_use = decode[22];
assign ID_rs2_use = decode[23];
assign ID_rs1=ID_inst[19:15];
assign ID_rs2=ID_inst[24:20];
assign ID_rd =ID_inst[11:7];
assign ID_re_mem = decode[24];
assign ID_csr_we = decode[25];

decoder decoder(.comb_decode_inst(ID_inst),
                .comb_decode(decode)
);//decoder

// wire [4:0] write_addr =  WB_wb_sel== 2'b00 ?( :); 
Regs regs(
        .clk(clk),
        .rst(rst),
        .we(WB_we_reg),
        .read_addr_1(ID_inst[19:15]),
        .read_addr_2(ID_inst[24:20]),
        .write_addr(WB_inst[11:7]),
        .write_data(dataW),
        .switch_mode(switch_mode),

        .read_data_1(ID_data1),
        .read_data_2(ID_data2),
        .cosim_regs(cosim_regs)
);//reg

immgen imm_gen(
        .imm_in(ID_inst[31:0]),
        .immgen_op(ID_immgen_op),
        .imm(ID_imm)
);//imm_generater

wire [63:0] csr_val_id;
wire [63:0] CSR_WDATA;
wire [11:0] csr_addr_wb = WB_inst[31:20];
wire [11:0] csr_addr_id = ID_inst[31:20];


CSRModule csrmodule(
    .clk(clk),
    .rst(rst),
    .csr_we_wb(WB_csr_we),
    .csr_addr_wb(csr_addr_wb),
    .csr_val_wb(WB_csr_res),
    .csr_addr_id(csr_addr_id),
    .csr_val_id(ID_csr_val),

    .pc_wb(WB_pc),
    .inst_wb(WB_inst),
    .valid_wb(WB_valid),
    .time_out(time_out), 
    .csr_ret_wb(csr_ret_wb),
    .csr_we_wb_temp(),
    .except_wb(WB_except),

    .priv(priv),
    .switch_mode(switch_mode),
    .pc_csr(csr_call_pc),

    .cosim_interrupt(cosim_interrupt),
    .cosim_cause(cosim_cause),
    .cosim_csr_info(cosim_csr_info)
);

wire S_mode = priv == 2'b01;
wire M_mode = priv == 2'b11;

wire is_ecall_id = ID_inst == 32'h00000073;
wire is_ebreak_id = ID_inst == 32'h00100073;
IDExceptExamine IDExamine(
    .clk(clk),
    .rst(rst),
    .stall(IDEXE_stall),
    .flush(IDEXE_flush),

    .pc_id(ID_pc),
    .priv(priv),
    .is_ecall_id(is_ecall_id),
    .is_ebreak_id(is_ebreak_id),
    .illegal_id(),
    .inst_id(ID_inst),
    .valid_id(ID_valid),
    
    .except_id(ID_except),
    .except_exe(EXE_except),
    .except_happen_id(except_happen_id)
);

/*----------------------------------------ID/EXE----------------------------------------*/


IDEXE ID_EXE(
        .clk(clk),
        .rst(rst),
        .stall(IDEXE_stall),
        .flush(IDEXE_flush),
        .ID_pc(ID_pc),
        .ID_inst(ID_inst),
        .ID_valid(ID_valid),
        .ID_data1(ID_data1),
        .ID_data2(ID_data2),
        .ID_rs1(ID_rs1),
        .ID_rs2(ID_rs2),
        .ID_rd(ID_rd),
        .ID_imm(ID_imm),
        .ID_rs1_use(ID_rs1_use),
        .ID_rs2_use(ID_rs2_use),
        .ID_we_reg(ID_we_reg),
        .ID_we_mem(ID_we_mem),
        .ID_alu_op(ID_alu_op),
        .ID_bralu_op(ID_bralu_op),
        .ID_alu_asel(ID_alu_asel),
        .ID_alu_bsel(ID_alu_bsel),
        .ID_wb_sel(ID_wb_sel),
        .ID_data_width(ID_data_width),
        .ID_pc_4(ID_pc_4),
        .ID_npc_sel(ID_npc_sel),
        .ID_re_mem(ID_re_mem),
        .ID_csr_we(ID_csr_we),
        .ID_csr_val(ID_csr_val),
        .predict_jump_id(predict_jump_id),

        .EXE_pc(EXE_pc),
        .EXE_inst(EXE_inst),
        .EXE_valid(EXE_valid),
        .EXE_data1(EXE_data1),
        .EXE_data2(EXE_data2),
        .EXE_rs1(EXE_rs1),
        .EXE_rs2(EXE_rs2),
        .EXE_rd(EXE_rd),
        .EXE_imm(EXE_imm),
        .EXE_rs1_use(EXE_rs1_use),
        .EXE_rs2_use(EXE_rs2_use),
        .EXE_we_reg(EXE_we_reg),
        .EXE_we_mem(EXE_we_mem),
        .EXE_alu_op(EXE_alu_op),
        .EXE_bralu_op(EXE_bralu_op),
        .EXE_alu_asel(EXE_alu_asel),
        .EXE_alu_bsel(EXE_alu_bsel),
        .EXE_wb_sel(EXE_wb_sel),
        .EXE_data_width(EXE_data_width),
        .EXE_pc_4(EXE_pc_4),
        .EXE_npc_sel(EXE_npc_sel),
        .EXE_re_mem(EXE_re_mem),
        .EXE_csr_we(EXE_csr_we),
        .EXE_csr_val(EXE_csr_val),
        .predict_jump_exe(predict_jump_exe)
);

/*----------------------------------------EXE----------------------------------------*/
wire         EXE_br_taken;
wire  [63:0] EXE_alu_res;
wire  [63:0] EXE_pc;
wire  [31:0] EXE_inst;
wire         EXE_valid;
wire  [63:0] EXE_data1;
wire  [63:0] EXE_data2;
wire  [63:0] EXE_imm;
wire         EXE_we_reg;
wire  [3:0]  EXE_alu_op;
wire  [2:0]  EXE_bralu_op;
wire  [1:0]  EXE_alu_asel;
wire  [1:0]  EXE_alu_bsel;
wire  [1:0]  EXE_wb_sel;
wire  [2:0]  EXE_data_width;
wire  [63:0] EXE_pc_4;
wire  [63:0] alu_a,alu_b;
wire  [4:0]  EXE_rd;
wire  [4:0]  EXE_rs1,EXE_rs2;
wire         EXE_rs1_use,EXE_rs2_use;
wire         EXE_npc_sel;
wire         EXE_re_mem;
wire         EXE_we_mem;
wire  [63:0] EXE_csr_val;
wire  [63:0] Ain,Bin;
reg          forward_lockA,forward_lockB;
reg   [63:0] locked_Forward_data1,locked_Forward_data2;
always @(posedge clk) begin
        if(~forward_lockA & ForwardA & mem_stall_cpu) begin
                forward_lockA = 1;
                locked_Forward_data1 = Forward_data1;
        end
        else if(forward_lockA & ~mem_stall_cpu)begin
                forward_lockA = 0;
        end

        if(~forward_lockB & ForwardB & mem_stall_cpu) begin
                forward_lockB = 1;
                locked_Forward_data2 = Forward_data2;
        end
        else if(forward_lockB & ~mem_stall_cpu)begin
                forward_lockB = 0;
        end
end

assign Ain = ForwardA ? Forward_data1 : (forward_lockA ? locked_Forward_data1 :EXE_data1);
assign Bin = ForwardB ? Forward_data2 : (forward_lockB ? locked_Forward_data2 :EXE_data2);

Mux a_mux(
        .sel(EXE_alu_asel),
        .a(0),
        .b(Ain),
        .c(EXE_pc),
        .d(0),
        .result(alu_a)
);//ALU mux


Mux b_mux(  
        .sel(EXE_alu_bsel),
        .a(0),
        .b(Bin),
        .c(EXE_imm),
        .d(0),
        .result(alu_b)
);//ALU mux


ALU ALU(.a(alu_a),
        .b(alu_b),
        .alu_op(EXE_alu_op),
        .res(EXE_alu_res)
);//ALU

wire [63:0] EXE_csr_res;
CSRhandler csrhandler(
        .csr_val_exe(EXE_csr_val),
        .EXE_inst(EXE_inst),
        .EXE_alu_res(EXE_alu_res),
        
        .EXE_csr_res(EXE_csr_res)
);

branchcomp branch_comp(
          .bralu_op(EXE_bralu_op),
          .mem_stall(mem_stall_cpu),
          .rs1(Ain),
          .rs2(Bin),
          .br_taken(EXE_br_taken)
);//branch


/*----------------------------------------EXE/MEM----------------------------------------*/
EXEMEM EXE_MEM(
        .clk(clk),
        .rst(rst),
        .stall(EXEMEM_stall),
        .flush(EXEMEM_flush),

        .EXE_pc(EXE_pc),
        .EXE_inst(EXE_inst),
        .EXE_valid(EXE_valid),
        .EXE_data1(Ain),
        .EXE_data2(Bin),
        .EXE_rs1(EXE_rs1),
        .EXE_rs2(EXE_rs2),
        .EXE_rd(EXE_rd),
        .EXE_rs1_use(EXE_rs1_use),
        .EXE_rs2_use(EXE_rs2_use),
        .EXE_we_reg(EXE_we_reg),
        .EXE_we_mem(EXE_we_mem),
        .EXE_wb_sel(EXE_wb_sel),
        .EXE_data_width(EXE_data_width),
        .EXE_pc_4(EXE_pc_4),
        .EXE_npc_sel(EXE_npc_sel),
        .EXE_alu_res(EXE_alu_res),
        .EXE_re_mem(EXE_re_mem),
        .EXE_except(EXE_except),
        .EXE_csr_we(EXE_csr_we),
        .EXE_csr_res(EXE_csr_res),
        .EXE_csr_val(EXE_csr_val),

        .MEM_pc(MEM_pc),
        .MEM_inst(MEM_inst),
        .MEM_valid(MEM_valid),
        .MEM_data1(MEM_data1),
        .MEM_data2(MEM_data2),
        .MEM_rs1(MEM_rs1),
        .MEM_rs2(MEM_rs2),
        .MEM_rd(MEM_rd),
        .MEM_rs1_use(MEM_rs1_use),
        .MEM_rs2_use(MEM_rs2_use),
        .MEM_we_reg(MEM_we_reg),
        .MEM_we_mem(MEM_we_mem),
        .MEM_wb_sel(MEM_wb_sel),
        .MEM_data_width(MEM_data_width),
        .MEM_pc_4(MEM_pc_4),
        .MEM_npc_sel(MEM_npc_sel),
        .MEM_alu_res(MEM_alu_res),
        .MEM_re_mem(MEM_re_mem),
        .MEM_except(MEM_except),
        .MEM_csr_we(MEM_csr_we),
        .MEM_csr_res(MEM_csr_res),
        .MEM_csr_val(MEM_csr_val)
);


/*----------------------------------------MEM----------------------------------------*/

wire  [63:0] MEM_pc;
wire  [31:0] MEM_inst;
wire         MEM_valid;
wire  [63:0] MEM_data1;
wire  [63:0] MEM_data2;
wire  [4:0]  MEM_rs1;
wire  [4:0]  MEM_rs2;
wire  [4:0]  MEM_rd;
wire         MEM_rs1_use;
wire         MEM_rs2_use;
wire         MEM_we_reg;
wire         MEM_we_mem;
wire  [1:0]  MEM_wb_sel;
wire  [2:0]  MEM_data_width;
wire  [63:0] MEM_pc_4;
wire         MEM_npc_sel;
wire  [63:0] MEM_alu_res;
wire  [63:0] MEM_mem;
wire         MEM_re_mem;
wire [63:0] WB_csr_res;
wire [63:0] MEM_csr_res;
wire [63:0] WB_csr_val;
wire [63:0] MEM_csr_val;
wire  [63:0] rw_rdata;
wire  [63:0] rw_wdata = MEM_data2 << (MEM_alu_res%8*8); // Data Pkg
wire  [63:0] rw_addr = MEM_alu_res;
wire  [7:0]  rw_wmask;
maskgen mask_gen(
        .alu(MEM_alu_res),
        .memdata_width(MEM_data_width),
        .rw_wmask(rw_wmask)
);//Generate the mask
/*
RAM Vram(
        .clk(clk),
        .rstn(rstn),
        .rw_wmode(EXE_we_mem),
        .rw_addr(rw_addr),
        .rw_wdata(rw_wdata),
        .rw_wmask(rw_wmask),
        .rw_rdata(rw_rdata),
        .ro_addr(ro_addr),
        .ro_rdata(ro_rdata)
);//RAM
*/

data_trunc data_trunc(
        .rw_rdata(rw_rdata),
        .alu(MEM_alu_res),
        .memdata_width(MEM_data_width),
        .mem(MEM_mem)
);

/*----------------------------------------MEM/WB----------------------------------------*/

MEMWB MEM_WB(
        .clk(clk),
        .rst(rst),
        .stall(MEMWB_stall),
        .flush(MEMWB_flush),
        .MEM_alu_res(MEM_alu_res),
        .MEM_pc_4(MEM_pc_4),
        .MEM_mem(MEM_mem),
        .MEM_we_reg(MEM_we_reg),
        .MEM_wb_sel(MEM_wb_sel),
        .MEM_valid(MEM_valid),
        .MEM_inst(MEM_inst),
        .MEM_pc(MEM_pc),
        .MEM_data1(MEM_data1),
        .MEM_data2(MEM_data2),
        .MEM_re_mem(MEM_re_mem),
        .MEM_except(MEM_except),
        .MEM_csr_we(MEM_csr_we),
        .MEM_csr_res(MEM_csr_res),
        .MEM_csr_val(MEM_csr_val),

        .WB_alu_res(WB_alu_res),
        .WB_pc_4(WB_pc_4),
        .WB_mem(WB_mem),
        .WB_we_reg(WB_we_reg),
        .WB_wb_sel(WB_wb_sel),
        .WB_valid(WB_valid),
        .WB_inst(WB_inst),
        .WB_pc(WB_pc),
        .WB_data1(WB_data1),
        .WB_data2(WB_data2),
        .WB_re_mem(WB_re_mem),
        .WB_except(WB_except),
        .WB_csr_we(WB_csr_we),
        .WB_csr_res(WB_csr_res),
        .WB_csr_val(WB_csr_val)
);


/*----------------------------------------WB----------------------------------------*/

wire  [63:0] WB_mem;
wire  [63:0] WB_alu_res;
wire  [63:0] WB_pc_4;
wire         WB_we_reg;
wire  [1:0]  WB_wb_sel;
wire         WB_valid;
wire   [31:0] WB_inst;
wire   [63:0] WB_pc;
wire   [63:0] WB_data1;
wire   [63:0] WB_data2;
wire          WB_re_mem;

Mux Reg_write_back(
        .sel(WB_wb_sel),
        .a(WB_csr_val),
        .b(WB_alu_res),
        .c(WB_mem),
        .d(WB_pc_4),
        .result(dataW)
);//Write back to reg



endmodule